package com.raimcomputing.pickforme.domain.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class AbstractDaoHibernateImpl<T extends Serializable, KeyType extends Serializable>
		extends HibernateDaoSupport {
	private Log log = LogFactory.getLog( AbstractDaoHibernateImpl.class );

	@SuppressWarnings("unchecked")
	protected Class<T> domainClass = getDomainClass();

	/**
	 * Method to return the class of the domain object
	 */
	@SuppressWarnings("unchecked")
	protected Class getDomainClass() {
		if ( domainClass == null ) {
			ParameterizedType thisType = (ParameterizedType) getClass()
					.getGenericSuperclass();
			domainClass = (Class) thisType.getActualTypeArguments()[0];
		}
		return domainClass;
	}

	@SuppressWarnings("unchecked")
	public T load( KeyType id ) {
		return (T) getHibernateTemplate().load( domainClass, id );
	}

	public void update( T t ) {
		getHibernateTemplate().update( t );
	}

	public void save( T t ) {
		getHibernateTemplate().save( t );
	}

	public void delete( T t ) {
		getHibernateTemplate().delete( t );
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		return (getHibernateTemplate().find( "from " + domainClass.getName()
				+ " x" ));
	}

	public void deleteById( KeyType id ) {
		Object obj = load( id );
		getHibernateTemplate().delete( obj );
	}

	public void deleteAll() {
		getHibernateTemplate().execute( new HibernateCallback() {
			public Object doInHibernate( Session session )
					throws HibernateException {
				String hqlDelete = "delete " + domainClass.getName();
				int deletedEntities = session.createQuery( hqlDelete )
						.executeUpdate();
				log.debug( deletedEntities + " elements of class "
						+ domainClass.getName() + " deleted." );
				return null;
			}
		} );
	}

	public int count() {
		List list = getHibernateTemplate().find(
				"select count(*) from " + domainClass.getName() + " x" );
		Integer count = (Integer) list.get( 0 );
		return count.intValue();
	}
}
